<template>
  <el-dialog
    :visible.sync="value"
    title="图片裁切"
    @close="cancel"
    destroy-on-close
  >
    <vue-cropper
      ref="cropper"
      :img="imgSrc"
      :info="true"
      :autoCropWidth="cropWidth"
      :autoCropHeight="cropHeight"
      :ready="cropImage"
      :auto-crop="true"
      :outputType="'jpg'"
      style="width: 100%; height: 420px"
      :fixed="true"
      :fixedNumber="[cropWidth, cropHeight]"
    ></vue-cropper>
    <span slot="footer" class="dialog-footer">
      <el-button @click="cancel">取 消</el-button>
      <el-button type="primary" @click="cropAndSubmit" :loading="loading">确 定</el-button>
    </span>
  </el-dialog>
</template>
<script>
import { VueCropper } from "vue-cropper"
import { createStorage, merchantPicUpload } from "@/api/business/storage"
import { getToken } from '@/utils/auth'
export default {
  name: "ImageCropper",
  components: {
    VueCropper
  },
  props: {
    value: {
      type: [Boolean],
      default: () => false
    },
    imgSrc: {
      type: [String],
      default: () => ""
    },
    cropWidth: {
      type: [Number],
      default: () => 200
    },
    cropHeight: {
      type: [Number],
      default: () => 100
    },
    aspectRatio: {
      type: [Number],
      default: () => 1
    }
  },
  data() {
    return {
      loading: false,
      currentSize: { width: 0, height: 0 },
    }
  },
  methods: {
    cropImage() {
      // 当裁切器准备就绪时调用（可选）
    },
    async cropAndSubmit() {
      this.loading = true;
      this.$refs.cropper.getCropData(async(data) => {
        const cropWidth = this.$refs.cropper.cropW
        const cropHeight = this.$refs.cropper.cropH
        console.log(`裁剪框宽度: ${cropWidth}, 裁剪框高度: ${cropHeight}`)
        const blob = await this.convertBase64ToResizedBlob(data, cropWidth, cropHeight)
        let formData = new FormData()
        formData.append("file", blob, new Date().getTime() + ".jpg")
        // 上传图片
        let promise = createStorage;
        if(!getToken()){
          // 完善信息页面和商户入驻页面，未登录时使用的接口
          promise = merchantPicUpload;
        }
        promise(formData).then((response) => {
          this.loading = false;
          this.$emit("uploadSuccess", response.data.data.url) // 保存上传图片后的地址
          this.$emit("input", false) // 关闭弹框
        }).catch(()=>{
          this.loading = false;
        })
      })
    },
    convertBase64ToResizedBlob(base64Image, targetWidth = 400, targetHeight = 300) {
      return new Promise((resolve, reject) => {
        // 1. 验证输入
        if (!base64Image || typeof base64Image !== 'string') {
          return reject(new Error('无效的 Base64 数据'))
        }
        const [header, data] = base64Image.split(',')
        if (!header || !data) {
          return reject(new Error('Base64 格式不正确，缺少头部或数据部分'))
        }

        // 2. 处理特殊字符（URL安全编码）
        const decodedData = decodeURIComponent(escape(data))
        // 2. 创建临时图像
        const img = new Image()
        img.crossOrigin = 'anonymous'
        let tempObjectUrl = null

        // 3. 图片加载成功处理
        img.onload = () => {
          try {
            // 创建画布
            const canvas = document.createElement('canvas')
            canvas.width = targetWidth
            canvas.height = targetHeight

            // 计算等比缩放
            const scale = Math.min(
              targetWidth / img.width,
              targetHeight / img.height
            )
            const scaledWidth = img.width * scale
            const scaledHeight = img.height * scale
            // 绘制图片（保持比例居中）
            const ctx = canvas.getContext('2d')
            ctx.clearRect(0, 0, targetWidth, targetHeight)
            ctx.drawImage(
              img,
              (targetWidth - scaledWidth) / 2,
              (targetHeight - scaledHeight) / 2,
              scaledWidth,
              scaledHeight
            )
            // 转换为 Blob
            const mimeType = base64Image.match(/:(.*?);/)[1] || 'image/jpeg'
            canvas.toBlob(blob => {
              // 清理资源
              if (tempObjectUrl) {
                window.URL.revokeObjectURL(tempObjectUrl)
              }
              // 验证结果
              if (!blob || blob.size === 0) {
                throw new Error('Blob 转换失败')
              }
              resolve(blob)
            }, mimeType, 0.9)

          } catch (error) {
            cleanup()
            reject(error)
          }
        }

        // 4. 图片加载失败处理
        img.onerror = (error) => {
          let errorMsg = '图片加载失败'
          // 尝试获取更详细的错误信息
          if (event && event.message) {
            errorMsg += `: ${event.message}`
          } else if (typeof navigator !== 'undefined' && navigator.userAgent.includes('Firefox')) {
            errorMsg += ' (Firefox 浏览器可能需要额外配置)'
          }

          cleanup()
          reject(new Error(errorMsg))
        }

        // 5. Base64 转 Object URL
        try {
          const bytes = window.atob(data)
          const byteArr = new ArrayBuffer(bytes.length)
          const chatArr = new Uint8Array(byteArr)
          for (let i = 0; i < bytes.length; i++) {
            chatArr[i] = bytes.charCodeAt(i)
          }
          tempObjectUrl = window.URL.createObjectURL(
            new Blob([byteArr], {
              type: header.match(/:(.*?);/)[1] || 'image/jpeg'
            })
          )
          img.src = tempObjectUrl
        } catch (error) {
          cleanup()
          reject(new Error(`Base64 解码失败: ${error.message}`))
        }

        // 清理函数
        function cleanup() {
          if (tempObjectUrl) {
            window.URL.revokeObjectURL(tempObjectUrl)
          }
        }
      })
    },
    convertBase64ToBlob(base64Image) {
      const [type, img] = base64Image.split(",")
      const bytes = window.atob(img)
      const byteArr = new ArrayBuffer(bytes.length)
      const chatArr = new Uint8Array(byteArr)
      for (let i = 0; i < bytes.length; i++) {
        chatArr[i] = bytes.charCodeAt(i)
      }
      return new Blob([byteArr], { type: "image/jpg" })
    },
    cancel() {
      this.$emit("input", false)
    }
  }
}
</script>
